package com.swak.fx.support.ui;

import org.controlsfx.glyphfont.FontAwesome;

import com.swak.utils.StringUtils;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;

/**
 * UIAction.
 * 
 * @author DELL
 */
public class UIAction extends GridPane implements UILifecycle {

	private final String STYLE_CLASS = "ui-action";
	private final String LEFT_STYLE_CLASS = "ui-action_left";
	private final String TEXT_STYLE_CLASS = "ui-action_text";
	private final String VALUE_STYLE_CLASS = "ui-action_value";
	private final String RIGHT_STYLE_CLASS = "ui-action_right";

	public UIAction() {
		this.init();
	}

	@Override
	public void initializeParts() {
		getStyleClass().add(STYLE_CLASS);
	}

	@Override
	public void layoutParts() {
		Node left = leftNodeProperty().get();
		Node text = textNodeProperty().get();
		Node value = valueNodeProperty().get();
		Node right = rightNodeProperty().get();
		this.initNode(left, LEFT_STYLE_CLASS);
		this.initNode(text, TEXT_STYLE_CLASS);
		this.initNode(value, VALUE_STYLE_CLASS);
		this.initNode(right, RIGHT_STYLE_CLASS);

		if (text != null) {
			GridPane.setHgrow(text, Priority.ALWAYS);
			if (!textNodeCenterProperty().get()) {
				GridPane.setHalignment(text, HPos.LEFT);
			}
		}
	}

	private void initNode(Node node, String style) {
		if (node == null) {
			return;
		}
		node.getStyleClass().add(style);
		GridPane.setVgrow(node, Priority.ALWAYS);
		GridPane.setHalignment(node, HPos.CENTER);
		GridPane.setValignment(node, VPos.CENTER);
	}

	@Override
	public void setupValueChangedListeners() {
		leftNodeProperty().addListener((ob, o, n) -> this.onChangeNode(o, n, 0));
		textNodeProperty().addListener((ob, o, n) -> this.onChangeNode(o, n, 1));
		valueNodeProperty().addListener((ob, o, n) -> this.onChangeNode(o, n, 2));
		rightNodeProperty().addListener((ob, o, n) -> this.onChangeNode(o, n, 3));
		textNodeCenterProperty().addListener((ob, o, n) -> {
			Node text = textNodeProperty().get();
			if (n && text != null) {
				GridPane.setHalignment(text, HPos.CENTER);
			} else if (text != null) {
				GridPane.setHalignment(text, HPos.LEFT);
			}
		});
		this.commandProperty.addListener((ob, o, n) -> {
			this.getProperties().put(UI.Conts.Cmd_Key, n);
		});
	}

	private void onChangeNode(Node o, Node n, int column) {
		this.getChildren().remove(o);
		this.getChildren().add(n);
		if (n != null) {
			GridPane.setConstraints(n, column, 0);
		}
		this.layoutParts();
	}

	@Override
	public void setupEventHandlers() {
		this.addEventHandler(MouseEvent.MOUSE_CLICKED, (e) -> {
			Node node = (Node) e.getTarget();
			if (this.hasProperties() && !node.hasProperties()) {
				this.copyBindProperties(node);
			}
		});
	}

	// 只拷贝 "Bind." 开头的属性
	private void copyBindProperties(Node node) {
		this.getProperties().entrySet().stream()
				.filter(entry -> StringUtils.startsWith(entry.getKey().toString(), UI.Conts.Pref_Key))
				.forEach(entry -> node.getProperties().put(entry.getKey(), entry.getValue()));
	}

	// ================================================================================
	// Properties
	// ================================================================================
	private final BooleanProperty textNodeCenterProperty = new SimpleBooleanProperty(true);
	private final ObjectProperty<Node> leftNodeProperty = new SimpleObjectProperty<Node>(this, "left-node");
	private final ObjectProperty<Node> textNodeProperty = new SimpleObjectProperty<Node>(this, "text-node");
	private final ObjectProperty<Node> valueNodeProperty = new SimpleObjectProperty<Node>(this, "value-node");
	private final ObjectProperty<Node> rightNodeProperty = new SimpleObjectProperty<Node>(this, "right-node");
	private final ObjectProperty<Object> commandProperty = new SimpleObjectProperty<>();

	public ObjectProperty<Node> leftNodeProperty() {
		return leftNodeProperty;
	}

	public ObjectProperty<Node> textNodeProperty() {
		return textNodeProperty;
	}

	public ObjectProperty<Node> valueNodeProperty() {
		return valueNodeProperty;
	}

	public ObjectProperty<Node> rightNodeProperty() {
		return rightNodeProperty;
	}

	public BooleanProperty textNodeCenterProperty() {
		return textNodeCenterProperty;
	}

	public UIAction setLeftNode(Node node) {
		leftNodeProperty().set(node);
		return this;
	}

	public UIAction setRightNode(Node node) {
		rightNodeProperty().set(node);
		return this;
	}

	public UIAction setTextNode(Node node) {
		textNodeProperty().set(node);
		return this;
	}

	public UIAction setIcon(FontAwesome.Glyph icon) {
		if (icon != null) {
			leftNodeProperty().set(new UIIcon(icon));
		}
		return this;
	}

	public UIAction setText(String node) {
		textNodeProperty().set(new UILabel(node));
		return this;
	}

	public UIAction setTextCenter(boolean bol) {
		textNodeCenterProperty().set(bol);
		return this;
	}

	public UIAction setValueNode(Node node) {
		valueNodeProperty().set(node);
		return this;
	}

	public UIAction setCommand(Object cmd) {
		this.commandProperty.set(cmd);
		return this;
	}
}